package com.yeskery.nut.extend.datasource.druid;

import com.alibaba.druid.pool.DruidDataSource;
import com.yeskery.nut.application.ServerEventContext;
import com.yeskery.nut.extend.datasource.DataSourcePlugin;
import com.yeskery.nut.plugin.ApplicationContextSupportBasePlugin;
import com.yeskery.nut.plugin.PluginBeanMetadata;
import com.yeskery.nut.util.StringUtils;

import javax.sql.DataSource;
import java.util.Collection;
import java.util.Collections;
import java.util.function.Consumer;

/**
 * Druid连接池插件
 * @author sprout
 * @version 1.0
 * 2022-07-10 18:55
 */
public class DruidPlugin extends ApplicationContextSupportBasePlugin implements DataSourcePlugin {

    /** JDBC驱动类名称 */
    private final String driverClassName;

    /** JDBC URL */
    private final String url;

    /** JDBC 用户名 */
    private final String username;

    /** JDBC 密码 */
    private final String password;

    /** 数据源消费者 */
    private final Consumer<DruidDataSource> dataSourceConsumer;

    /** 连接池对象 */
    private DruidDataSource dataSource;

    /**
     * 构建Druid连接池插件
     * @param driverClassName JDBC驱动类名称
     * @param url JDBC URL
     * @param username JDBC 用户名
     * @param password JDBC 密码
     */
    public DruidPlugin(String driverClassName, String url, String username, String password) {
        this(driverClassName, url, username, password, null);
    }

    /**
     * 构建Druid连接池插件
     * @param driverClassName JDBC驱动类名称
     * @param url JDBC URL
     * @param username JDBC 用户名
     * @param password JDBC 密码
     * @param consumer 数据源消费者
     */
    public DruidPlugin(String driverClassName, String url, String username, String password, Consumer<DruidDataSource> consumer) {
        this.driverClassName = driverClassName;
        this.url = url;
        this.username = username;
        this.password = password;
        this.dataSourceConsumer = consumer;
    }

    @Override
    protected Collection<PluginBeanMetadata> getRegisterPluginBeanMetadata() {
        dataSource = new DruidDataSource();
        if (!StringUtils.isEmpty(driverClassName)) {
            dataSource.setDriverClassName(driverClassName);
        }
        if (!StringUtils.isEmpty(url)) {
            dataSource.setUrl(url);
        }
        if (!StringUtils.isEmpty(username)) {
            dataSource.setUsername(username);
        }
        if (!StringUtils.isEmpty(password)) {
            dataSource.setPassword(password);
        }
        initialized(dataSource);
        if (dataSourceConsumer != null) {
            dataSourceConsumer.accept(dataSource);
        }
        return Collections.singletonList(new PluginBeanMetadata("dataSource", dataSource,
                DataSource.class, DruidDataSource.class));
    }

    @Override
    public DataSource getDataSource() {
        return dataSource;
    }

    @Override
    public void beforeClose(ServerEventContext serverEventContext) {
        if (dataSource != null) {
            dataSource.close();
        }
    }

    /**
     * 初始化Druid数据源
     * @param dataSource Druid数据源
     */
    private void initialized(DruidDataSource dataSource) {
        dataSource.setMaxActive(20);
        dataSource.setInitialSize(5);
        dataSource.setMaxWait(6000);
        dataSource.setMinIdle(1);
        dataSource.setTimeBetweenEvictionRunsMillis(60000);
        dataSource.setMinEvictableIdleTimeMillis(300000);
        dataSource.setTestWhileIdle(true);
        dataSource.setTestOnBorrow(false);
        dataSource.setTestOnReturn(false);
        dataSource.setPoolPreparedStatements(true);
        dataSource.setMaxOpenPreparedStatements(20);
        dataSource.setAsyncInit(true);
    }
}
